package cc.magicjson.example.demo.thead.scheduler;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
 * 定义一个酸度检测事件发布者类
 */
class PhDetectionEventPublisher {
    /**
     * 是否触发的信号 使用原子类保证线程安全
     */
    private final AtomicBoolean isTriggered = new AtomicBoolean(false);

    /**
     * 触发酸度检测事件
     *  如果获取返回true则设置执行信号true
     *  如果没有则默认false
     */
	public void triggerPhDetection() {
        // 在此实现获取酸度信号获得返回信号true
        System.out.println("收到酸度检测信号...");
        // 获取后设置信号为true 此处是为了发送事件信号表示
        // 已经触发了酸度检测 [if(true){isTriggered.set(true);} 这里是生产代码]
		isTriggered.set(true);

	}

    /**
     * 获取触发酸度检测事件信号
     * public final boolean getAndSet(boolean newValue) {
     *         return (int)VALUE.getAndSet(this, (newValue ? 1 : 0)) != 0;
     *     }
     *  该方法优先返回当前的  isTriggered 如果没有则设置传入的false
     * @return 是否触发酸度检测事件信号
     */
	public boolean isTriggered() {
		return isTriggered.getAndSet(false);
	}
}

// 主类
public class AcidDetectionScheduler {
	private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
	private final PhDetectionEventPublisher eventPublisher = new PhDetectionEventPublisher();
	private boolean dailyTasksCompleted = false;

	public void startDailyTasks() {
		Runnable dailyTask = () -> {
			performBlankDetection();
			performStandardDetection();
			dailyTasksCompleted = true;
		};

		// 安排每天执行一次任务，第一次立即执行，然后每24小时执行一次TimeUnit.HOURS）
        // 这里为了演示改成24秒执行一次空白与标准检测
		scheduler.scheduleAtFixedRate(dailyTask, 0, 24, TimeUnit.SECONDS);
	}

	public void performBlankDetection() {
		System.out.println("执行空白检测...");
		// 在此实现空白检测逻辑
	}

	public void performStandardDetection() {
		System.out.println("执行标准检测...");
		// 在此实现标准检测逻辑
	}

    /**
     * 酸度检测信号心跳检测及其执行
     * 酸度检测每秒心跳检查
     *  -如果发现酸度信号为true则执行酸度检测
     *  -如果发现false则不执行 继续心跳检查
     *
     */
	public void startIrregularPhDetection() {
		scheduler.scheduleAtFixedRate(() -> {
            //此处注释的是触发酸度检测信号的的方法 于生产中使用 详见 triggerPhDetection
//            eventPublisher.triggerPhDetection();
            boolean isTriggered = eventPublisher.isTriggered();
            System.out.println("当前信号:"+ isTriggered);
			if (isTriggered && dailyTasksCompleted) {
				performPhDetection();
			}
		}, 0, 1, TimeUnit.SECONDS); // 每秒检查一次是否有信号
	}

	public void performPhDetection() {
		System.out.println("执行酸度检测...");
		// 在此实现酸度检测逻辑
	}

    /**
     * 模拟接收不定时信号的方法 此处是模拟酸度信号的不定时发送 为了触发酸度信号
     */
	public void receiveSignal() {
		new Thread(() -> {
			try {
				while (true) {
					// 随机休眠一段时间以模拟不定时触发
					Thread.sleep((long) (Math.random() * 10000));
					eventPublisher.triggerPhDetection();
				}
			} catch (InterruptedException e) {
				Thread.currentThread().interrupt();
			}
		}).start();
	}

	public static void main(String[] args) {
        // 执行的主体流程
		AcidDetectionScheduler scheduler = new AcidDetectionScheduler();
        // 开启日常的定时任务检测
		scheduler.startDailyTasks();
        // 开启酸度检测
		scheduler.startIrregularPhDetection();
        // 启动模拟信号接收 这里为模拟实际中需要注释删除该代码
		scheduler.receiveSignal();
	}
}
